<!DOCTYPE html>

<html lang="
zh-CN"
    >

        <head>
            
                <title>
                    
                        JAVA-MyBatis -
                            
                                shanX&#39;s Blog
                </title>
                <meta charset="UTF-8">
                <meta name="description" content="">
                <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5">
                
                    

                        <link rel="shortcut icon" href="/image/author.png" type="image/png" />
                        <meta name="description" content="MyBatis">
<meta property="og:type" content="article">
<meta property="og:title" content="JAVA-MyBatis">
<meta property="og:url" content="https://rhymexmove.github.io/2021/05/03/5fd29565f315/index.html">
<meta property="og:site_name" content="shanX&#39;s Blog">
<meta property="og:description" content="MyBatis">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://rhymexmove.github.io/2021/05/03/5fd29565f315/image/article/JAVA-MyBatis-20210503/2020062316474822.png">
<meta property="og:image" content="https://rhymexmove.github.io/2021/05/03/5fd29565f315/image/article/JAVA-MyBatis-20210503/20200623164809990.png">
<meta property="og:image" content="https://rhymexmove.github.io/2021/05/03/5fd29565f315/image/article/JAVA-MyBatis-20210503/20200623164833872.png">
<meta property="og:image" content="https://rhymexmove.github.io/2021/05/03/5fd29565f315/image/article/JAVA-MyBatis-20210503/20200623164845962.png">
<meta property="og:image" content="https://rhymexmove.github.io/2021/05/03/5fd29565f315/image/article/JAVA-MyBatis-20210503/20200623164853569.png">
<meta property="og:image" content="https://rhymexmove.github.io/2021/05/03/5fd29565f315/image/article/JAVA-MyBatis-20210503/20200623164901861.png">
<meta property="og:image" content="https://rhymexmove.github.io/2021/05/03/5fd29565f315/image/article/JAVA-MyBatis-20210503/20200623164920502.png">
<meta property="og:image" content="https://rhymexmove.github.io/2021/05/03/5fd29565f315/image/article/JAVA-MyBatis-20210503/2020062316493391.png">
<meta property="og:image" content="https://rhymexmove.github.io/2021/05/03/5fd29565f315/image/article/JAVA-MyBatis-20210503/20200623164958936.png">
<meta property="og:image" content="https://rhymexmove.github.io/2021/05/03/5fd29565f315/image/article/JAVA-MyBatis-20210503/20200623165014965.png">
<meta property="og:image" content="https://rhymexmove.github.io/2021/05/03/5fd29565f315/image/article/JAVA-MyBatis-20210503/20200623165030775.png">
<meta property="og:image" content="https://rhymexmove.github.io/2021/05/03/5fd29565f315/image/article/JAVA-MyBatis-20210503/20200623165129955.png">
<meta property="og:image" content="https://rhymexmove.github.io/2021/05/03/5fd29565f315/image/article/JAVA-MyBatis-20210503/20200623165404113.png">
<meta property="article:published_time" content="2021-05-02T17:40:46.000Z">
<meta property="article:modified_time" content="2022-04-07T17:25:27.687Z">
<meta property="article:author" content="shanX">
<meta property="article:tag" content="狂神说">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://rhymexmove.github.io/2021/05/03/5fd29565f315/image/article/JAVA-MyBatis-20210503/2020062316474822.png">
                            <link rel="stylesheet" href="https://cdn.jsdelivr.net/combine/npm/highlight.js@9.15.8/styles/atom-one-dark.css,gh/theme-nexmoe/hexo-theme-nexmoe@latest/source/lib/mdui_043tiny/css/mdui.css,gh/theme-nexmoe/hexo-theme-nexmoe@latest/source/lib/iconfont/iconfont.css,gh/fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css?v=233"
                                crossorigin>
                            <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/justifiedGallery@3.8.1/dist/css/justifiedGallery.min.css">
                            <!--适用于 Retina 屏的 iPad-->
                            <link rel="apple-touch-icon-precomposed" sizes="144x144" href="https://cdn.jsdelivr.net/gh/RhymeXmove/blogimg@latest/author.png">
                            <!--适用于 Retina 屏的 iPhone-->
                            <link rel="apple-touch-icon-precomposed" sizes="120x120" href="https://cdn.jsdelivr.net/gh/RhymeXmove/blogimg@latest/author.png">
                            <!--适用于非 Retina 屏的 iPad-->
                            <link rel="apple-touch-icon-precomposed" sizes="72x72" href="https://cdn.jsdelivr.net/gh/RhymeXmove/blogimg@latest/author.png">
                            <!--适用于非 Retina 屏的 iPhone-->
                            <link rel="apple-touch-icon-precomposed" href="https://cdn.jsdelivr.net/gh/RhymeXmove/blogimg@latest/author.png">
                            
                                <link rel="stylesheet" href="//at.alicdn.com/t/font_2490857_fmjyoao96km.css">
                                
                                    <link rel="stylesheet" href="/css/style.css?v=1649858550910">
        <meta name="generator" content="Hexo 5.4.0"></head>

        <body class="mdui-drawer-body-left">
            
                <div id="nexmoe-background">
                    <div class="nexmoe-bg" style="background-image: url(https://cdn.jsdelivr.net/gh/RhymeXmove/blogimg@latest/cover/5887c2f1-b191-4890-aab5-2ce62d9955df.jpg)"></div>
                    <div class="mdui-appbar mdui-shadow-0">
                        <div class="mdui-toolbar">
                            <a mdui-drawer="{target: '#drawer', swipe: true}" title="menu" class="mdui-btn mdui-btn-icon mdui-ripple"><i class="mdui-icon nexmoefont icon-menu"></i></a>
                            <div class="mdui-toolbar-spacer"></div>
                            <!--<a href="javascript:;" class="mdui-btn mdui-btn-icon"><i class="mdui-icon material-icons">search</i></a>-->
                            <a href="/" title="shanX" class="mdui-btn mdui-btn-icon"><img src="https://cdn.jsdelivr.net/gh/RhymeXmove/blogimg@latest/author.png" alt="shanX"></a>
                        </div>
                    </div>
                </div>
                <div id="nexmoe-header">
                    <div class="nexmoe-drawer mdui-drawer" id="drawer">
    <div class="nexmoe-avatar mdui-ripple">
        <a href="/" title="shanX">
            <img src="https://cdn.jsdelivr.net/gh/RhymeXmove/blogimg@latest/author.png" alt="shanX" alt="shanX">
        </a>
    </div>
    <div class="nexmoe-count nexmoe-widget-wrap">
        <div><span>文章</span>30</div>
        <div><span>标签</span>16</div>
        <div><span>分类</span>8</div>
    </div>
    <div class="nexmoe-list mdui-list nexmoe-widget-wrap" mdui-collapse="{accordion: true}">
        
        <a class="nexmoe-list-item mdui-list-item mdui-ripple" href="/" title="回到首页">
            <i class="mdui-list-item-icon nexmoefont icon-home"></i>
            <div class="mdui-list-item-content">
                回到首页
            </div>
        </a>
        
        <a class="nexmoe-list-item mdui-list-item mdui-ripple" href="/archives.html" title="文章归档">
            <i class="mdui-list-item-icon nexmoefont icon-container"></i>
            <div class="mdui-list-item-content">
                文章归档
            </div>
        </a>
        
        <a class="nexmoe-list-item mdui-list-item mdui-ripple" href="/cesium-test/index.html" title="Cesium">
            <i class="mdui-list-item-icon nexmoefont icon-Cesium-copy"></i>
            <div class="mdui-list-item-content">
                Cesium
            </div>
        </a>
        
        <a class="nexmoe-list-item mdui-list-item mdui-ripple" href="/cesium-covid/index.html" title="全球疫情">
            <i class="mdui-list-item-icon nexmoefont icon-areachart"></i>
            <div class="mdui-list-item-content">
                全球疫情
            </div>
        </a>
        
        <a class="nexmoe-list-item mdui-list-item mdui-ripple" href="/about.html" title="关于博客">
            <i class="mdui-list-item-icon nexmoefont icon-info-circle"></i>
            <div class="mdui-list-item-content">
                关于博客
            </div>
        </a>
        
    </div>
    <aside id="nexmoe-sidebar">
  
  <div class="nexmoe-widget-wrap">
    <div class="nexmoe-widget nexmoe-search">
        <form id="search_form" action_e="https://cn.bing.com/search?q=rhymexmove.github.io" onsubmit="return search();">
            <label><input id="search_value" name="q" type="search" placeholder="搜索"></label>
        </form>
    </div>
</div>
  
  <div class="nexmoe-widget-wrap">
    <div class="nexmoe-widget nexmoe-social">
        <a class="mdui-ripple" href="https://space.bilibili.com/20666214" target="_blank" mdui-tooltip="{content: '哔哩哔哩'}" style="color: rgb(231, 106, 141);background-color: rgba(231, 106, 141, .15);">
            <i class="nexmoefont icon-bilibili"></i>
        </a><a class="mdui-ripple" href="https://github.com/RhymeXmove/" target="_blank" mdui-tooltip="{content: 'GitHub'}" style="color: rgb(231, 106, 141);background-color: rgba(231, 106, 141, .15);">
            <i class="nexmoefont icon-github"></i>
        </a><a class="mdui-ripple" href="https://gitee.com/shanxin123/" target="_blank" mdui-tooltip="{content: 'Gitee'}" style="color: rgb(220,20,60);background-color: rgba(220,20,60, .15);">
            <i class="nexmoefont icon-gitee"></i>
        </a>
    </div>
</div>
  
  
    <div class="nexmoe-widget-wrap">
        <h3 class="nexmoe-widget-title">
            文章分类
        </h3>
        <div class="nexmoe-widget">

            <ul class="category-list">

                


                    

                        

                            <li class="category-list-item">
                                <a class="category-list-link" href="/categories/mysql/">
                                    -mysql
                                </a>
                                <span class="category-list-count">1</span>
                            </li>

                            

                            <li class="category-list-item">
                                <a class="category-list-link" href="/categories/Cesium/">
                                    Cesium
                                </a>
                                <span class="category-list-count">3</span>
                            </li>

                            

                            <li class="category-list-item">
                                <a class="category-list-link" href="/categories/DB/">
                                    DB
                                </a>
                                <span class="category-list-count">2</span>
                            </li>

                            

                            <li class="category-list-item">
                                <a class="category-list-link" href="/categories/Leetcode/">
                                    Leetcode
                                </a>
                                <span class="category-list-count">4</span>
                            </li>

                            

                            <li class="category-list-item">
                                <a class="category-list-link" href="/categories/Vue/">
                                    Vue
                                </a>
                                <span class="category-list-count">2</span>
                            </li>

                            

                            <li class="category-list-item">
                                <a class="category-list-link" href="/categories/blog搭建/">
                                    blog搭建
                                </a>
                                <span class="category-list-count">1</span>
                            </li>

                            

                            <li class="category-list-item">
                                <a class="category-list-link" href="/categories/java/">
                                    java
                                </a>
                                <span class="category-list-count">12</span>
                            </li>

                            

                            <li class="category-list-item">
                                <a class="category-list-link" href="/categories/资源/">
                                    资源
                                </a>
                                <span class="category-list-count">1</span>
                            </li>

                            
            </ul>

        </div>
    </div>
    
  
  
  <div class="nexmoe-widget-wrap">
    <div id="randomtagcloud" class="nexmoe-widget tagcloud nexmoe-rainbow">
      <a href="/tags/DB/" style="font-size: 10px;">-DB</a> <a href="/tags/Cesium/" style="font-size: 12.5px;">Cesium</a> <a href="/tags/GIS/" style="font-size: 10px;">GIS</a> <a href="/tags/Leetcode/" style="font-size: 15px;">Leetcode</a> <a href="/tags/Vue/" style="font-size: 12.5px;">Vue</a> <a href="/tags/blog%E6%90%AD%E5%BB%BA/" style="font-size: 10px;">blog搭建</a> <a href="/tags/echart/" style="font-size: 10px;">echart</a> <a href="/tags/java/" style="font-size: 10px;">java</a> <a href="/tags/java%E5%9F%BA%E7%A1%80/" style="font-size: 20px;">java基础</a> <a href="/tags/mysql/" style="font-size: 10px;">mysql</a> <a href="/tags/spring/" style="font-size: 10px;">spring</a> <a href="/tags/vue/" style="font-size: 10px;">vue</a> <a href="/tags/%E6%89%B9%E5%A4%84%E7%90%86%E5%B7%A5%E5%85%B7/" style="font-size: 10px;">批处理工具</a> <a href="/tags/%E6%95%B0%E6%8D%AE%E5%BA%93/" style="font-size: 10px;">数据库</a> <a href="/tags/%E7%8B%82%E7%A5%9E%E8%AF%B4/" style="font-size: 17.5px;">狂神说</a> <a href="/tags/%E8%B5%84%E6%BA%90/" style="font-size: 10px;">资源</a>
    </div>
    
  </div>

  
  
  <div class="nexmoe-widget-wrap">
    <h3 class="nexmoe-widget-title">文章归档</h3>
    <div class="nexmoe-widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2022/">2022</a><span class="archive-list-count">1</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2021/">2021</a><span class="archive-list-count">29</span></li></ul>
    </div>
  </div>



  
  
  <div class="nexmoe-widget-wrap">
    <h3 class="nexmoe-widget-title">最新文章</h3>
    <div class="nexmoe-widget">
      <ul>
        
          <li>
            <a href="/2022/04/13/7533e8f3cb4c/">mysql查询数据库内全部表名；查询表内全部字段名</a>
          </li>
        
          <li>
            <a href="/2021/09/26/ee931b51117c/">什么是计算机图形学？</a>
          </li>
        
          <li>
            <a href="/2021/09/08/9adeea845004/">中国城市坐标(包含市辖区)</a>
          </li>
        
          <li>
            <a href="/2021/08/31/7ba201dda6cb/">Cesium billboard贴地形表</a>
          </li>
        
          <li>
            <a href="/2021/08/09/0d3ed7d31d83/">Vue中使用Vue-jsonp请求jsonp数据</a>
          </li>
        
      </ul>
    </div>
  </div>

  
</aside>
    <div class="nexmoe-copyright">
        &copy; 2022 shanX
        Powered by <a href="http://hexo.io/" target="_blank">Hexo</a>
        & <a href="https://github.com/theme-nexmoe/hexo-theme-nexmoe" target="_blank">Nexmoe</a>
        
    </div>
</div><!-- .nexmoe-drawer -->
                </div>
                <div id="nexmoe-content">
                    <div class="nexmoe-primary">
                        <div class="nexmoe-post">

  <div class="nexmoe-post-right">
    
      <div class="nexmoe-fixed">
        <div class="nexmoe-valign">
            <div class="nexmoe-toc">
                
                
                  <ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#MyBatis"><span class="toc-number">1.</span> <span class="toc-text">MyBatis</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%AE%80%E4%BB%8B"><span class="toc-number">1.1.</span> <span class="toc-text">简介</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BB%80%E4%B9%88%E6%98%AF%E6%8C%81%E4%B9%85%E5%8C%96%EF%BC%9F"><span class="toc-number">1.2.</span> <span class="toc-text">什么是持久化？</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%8C%81%E4%B9%85%E5%B1%82"><span class="toc-number">1.3.</span> <span class="toc-text">持久层</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B8%BA%E4%BB%80%E4%B9%88%E9%9C%80%E8%A6%81Mybatis%EF%BC%9F"><span class="toc-number">1.4.</span> <span class="toc-text">为什么需要Mybatis？</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%AC%AC%E4%B8%80%E4%B8%AAMyBatis%E7%A8%8B%E5%BA%8F-mybatis-01"><span class="toc-number">1.5.</span> <span class="toc-text">第一个MyBatis程序 mybatis-01</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#CRUD"><span class="toc-number">2.</span> <span class="toc-text">CRUD</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#1%E3%80%81namespace"><span class="toc-number">2.1.</span> <span class="toc-text">1、namespace</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2%E3%80%81select"><span class="toc-number">2.2.</span> <span class="toc-text">2、select</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%A2%9E%E5%88%A0%E6%94%B9%E9%9C%80%E8%A6%81%E6%8F%90%E4%BA%A4%E4%BA%8B%E5%8A%A1"><span class="toc-number">2.3.</span> <span class="toc-text">增删改需要提交事务</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3%E3%80%81insert-update-delete"><span class="toc-number">2.4.</span> <span class="toc-text">3、insert,update,delete</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E4%B8%87%E8%83%BDMap"><span class="toc-number">3.</span> <span class="toc-text">万能Map</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E6%A8%A1%E7%B3%8A%E6%9F%A5%E8%AF%A2"><span class="toc-number">4.</span> <span class="toc-text">模糊查询</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E9%85%8D%E7%BD%AE%E4%B9%8B%E5%B1%9E%E6%80%A7%E4%BC%98%E5%8C%96mybatis-02"><span class="toc-number">5.</span> <span class="toc-text">配置之属性优化mybatis-02</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%A0%B8%E5%BF%83%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6"><span class="toc-number">5.1.</span> <span class="toc-text">核心配置文件</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE"><span class="toc-number">5.2.</span> <span class="toc-text">环境配置</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%B1%9E%E6%80%A7%EF%BC%88properties%EF%BC%89"><span class="toc-number">5.3.</span> <span class="toc-text">属性（properties）</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%B1%BB%E5%9E%8B%E5%88%AB%E5%90%8D"><span class="toc-number">5.4.</span> <span class="toc-text">类型别名</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E8%AE%BE%E7%BD%AE-Settings"><span class="toc-number">5.5.</span> <span class="toc-text">设置 Settings</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%85%B6%E4%BB%96%E9%85%8D%E7%BD%AE"><span class="toc-number">5.6.</span> <span class="toc-text">其他配置</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%98%A0%E5%B0%84%E5%99%A8-mappers"><span class="toc-number">5.7.</span> <span class="toc-text">映射器 mappers</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BD%9C%E7%94%A8%E5%9F%9F%E5%92%8C%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F"><span class="toc-number">5.8.</span> <span class="toc-text">作用域和生命周期</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E8%A7%A3%E5%86%B3%E5%B1%9E%E6%80%A7%E5%90%8D%E5%92%8C%E5%AD%97%E6%AE%B5%E5%90%8D%E4%B8%8D%E4%B8%80%E8%87%B4%E7%9A%84%E9%97%AE%E9%A2%98"><span class="toc-number">6.</span> <span class="toc-text">解决属性名和字段名不一致的问题</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%97%AE%E9%A2%98"><span class="toc-number">6.0.1.</span> <span class="toc-text">问题</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#resultMap"><span class="toc-number">6.0.2.</span> <span class="toc-text">resultMap</span></a></li></ol></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E6%97%A5%E5%BF%97"><span class="toc-number">7.</span> <span class="toc-text">日志</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%97%A5%E5%BF%97%E5%B7%A5%E5%8E%82"><span class="toc-number">7.1.</span> <span class="toc-text">日志工厂</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Log4j"><span class="toc-number">7.2.</span> <span class="toc-text">Log4j</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E5%88%86%E9%A1%B5"><span class="toc-number">8.</span> <span class="toc-text">分页</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8Limit%E5%88%86%E9%A1%B5"><span class="toc-number">8.1.</span> <span class="toc-text">使用Limit分页</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#RowBounds%E5%88%86%E9%A1%B5"><span class="toc-number">8.2.</span> <span class="toc-text">RowBounds分页</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%88%86%E9%A1%B5%E6%8F%92%E4%BB%B6"><span class="toc-number">8.3.</span> <span class="toc-text">分页插件</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8%E6%B3%A8%E8%A7%A3%E5%BC%80%E5%8F%91"><span class="toc-number">9.</span> <span class="toc-text">使用注解开发</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E9%9D%A2%E5%90%91%E6%8E%A5%E5%8F%A3%E5%BC%80%E5%8F%91"><span class="toc-number">9.1.</span> <span class="toc-text">面向接口开发</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8%E6%B3%A8%E8%A7%A3%E5%BC%80%E5%8F%91-1"><span class="toc-number">9.2.</span> <span class="toc-text">使用注解开发</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%B3%A8%E8%A7%A3CURD"><span class="toc-number">9.3.</span> <span class="toc-text">注解CURD</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#Lombok"><span class="toc-number">10.</span> <span class="toc-text">Lombok</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E5%A4%9A%E5%AF%B9%E4%B8%80%E5%A4%84%E7%90%86"><span class="toc-number">11.</span> <span class="toc-text">多对一处理</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E4%B8%80%E5%AF%B9%E5%A4%9A%E5%A4%84%E7%90%86"><span class="toc-number">12.</span> <span class="toc-text">一对多处理</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA"><span class="toc-number">12.1.</span> <span class="toc-text">环境搭建</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%B0%8F%E7%BB%93"><span class="toc-number">12.1.1.</span> <span class="toc-text">小结</span></a></li></ol></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E5%8A%A8%E6%80%81SQL"><span class="toc-number">13.</span> <span class="toc-text">动态SQL</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83"><span class="toc-number">13.1.</span> <span class="toc-text">搭建环境</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#IF"><span class="toc-number">13.1.1.</span> <span class="toc-text">IF</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#choose-when-otherwise"><span class="toc-number">13.1.2.</span> <span class="toc-text">choose (when, otherwise)</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#trim%E3%80%81where%E3%80%81set"><span class="toc-number">13.1.3.</span> <span class="toc-text">trim、where、set</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#SQL%E7%89%87%E6%AE%B5"><span class="toc-number">13.1.4.</span> <span class="toc-text">SQL片段</span></a></li></ol></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E7%BC%93%E5%AD%98"><span class="toc-number">14.</span> <span class="toc-text">缓存</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%AE%80%E4%BB%8B-1"><span class="toc-number">14.1.</span> <span class="toc-text">简介</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#MyBatis%E7%BC%93%E5%AD%98"><span class="toc-number">14.2.</span> <span class="toc-text">MyBatis缓存</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B8%80%E7%BA%A7%E7%BC%93%E5%AD%98"><span class="toc-number">14.3.</span> <span class="toc-text">一级缓存</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BA%8C%E7%BA%A7%E7%BC%93%E5%AD%98"><span class="toc-number">14.4.</span> <span class="toc-text">二级缓存</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%BC%93%E5%AD%98%E5%8E%9F%E7%90%86"><span class="toc-number">14.5.</span> <span class="toc-text">缓存原理</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E8%87%AA%E5%AE%9A%E4%B9%89%E7%BC%93%E5%AD%98-ehcache"><span class="toc-number">14.6.</span> <span class="toc-text">自定义缓存-ehcache</span></a></li></ol></li></ol>
                
            </div>
        </div>
      </div>
    
  </div>

  <article>
    
        <div class="nexmoe-post-cover" style="padding-bottom: NaN%;"> 
            <img data-src="https://cdn.jsdelivr.net/gh/RhymeXmove/blogimg@latest/cover/MyBatis.png" data-sizes="auto" alt="JAVA-MyBatis" class="lazyload">
            <h1>JAVA-MyBatis</h1>
        </div>
    
    
    <div class="nexmoe-post-meta nexmoe-rainbow-fill" style="margin:10px 0!important;">
    <a><i class="nexmoefont icon-calendar-fill"></i>2021年05月03日</a>
    <a><i class="nexmoefont icon-areachart"></i>7.7k 字</a>
    <a><i class="nexmoefont icon-time-circle-fill"></i>大概 37 分钟</a>
</div>

    <h1 id="MyBatis"><a href="#MyBatis" class="headerlink" title="MyBatis"></a>MyBatis</h1><span id="more"></span>

<h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><ul>
<li>mybatis是一个持久层框架；</li>
<li>支持定制SQL、存储过程以及高级映射；</li>
<li>MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。</li>
<li>Mybatis可以使用简单的XML或注解来配置和映射原生类型、接口和java的POJO（Plain Old Java Objects，普通老式java对象）为数据库中的记录。</li>
</ul>
<h2 id="什么是持久化？"><a href="#什么是持久化？" class="headerlink" title="什么是持久化？"></a>什么是持久化？</h2><p>数据持久化</p>
<ul>
<li>持久化就是将程序的数据在持久状态和瞬间状态转化的过程；</li>
<li>内存：断电即失；</li>
<li>数据库（jdbc）, io文件持久化。</li>
<li>生活：冷藏、罐头；</li>
</ul>
<p>为什么需要持久化？</p>
<ul>
<li>有一些对象不能让丢掉；</li>
<li>内存在系统中很珍贵；</li>
</ul>
<h2 id="持久层"><a href="#持久层" class="headerlink" title="持久层"></a>持久层</h2><p>Dao层、Service层、Controller层…….</p>
<ul>
<li>完成持久化工作的代码块；</li>
<li>层界限十分明显。</li>
</ul>
<h2 id="为什么需要Mybatis？"><a href="#为什么需要Mybatis？" class="headerlink" title="为什么需要Mybatis？"></a>为什么需要Mybatis？</h2><ul>
<li>帮助程序员将数据存入到数据库中；</li>
<li>方便；</li>
<li>传统的JDBC代码太复杂了。简化。框架。自动化。</li>
<li>不用MyBatis也可以。但MyBatis更容易上手。技术没有高低之分</li>
<li>优点<ul>
<li>简单易学</li>
<li>灵活</li>
<li>sql和代码的分离，提高了可维护性。</li>
<li>提供映射标签，支持对象与数据库的orm字段映射。</li>
<li>提供对象关系映射标签，支持对象关系组件维护。</li>
<li>提供xml标签，支持编写动态sql。</li>
</ul>
</li>
</ul>
<p><strong>最重要的一点：使用的人多！</strong></p>
<h2 id="第一个MyBatis程序-mybatis-01"><a href="#第一个MyBatis程序-mybatis-01" class="headerlink" title="第一个MyBatis程序 mybatis-01"></a>第一个MyBatis程序 <code>mybatis-01</code></h2><ul>
<li>搭建环境</li>
</ul>
<pre><code class="sql">CREATE DATABASE `mybatis`;

USE `mybatis`;

CREATE TABLE `user` (
`id` INT(20) NOT NULL PRIMARY KEY,
`name` VARCHAR(30) DEFAULT NULL,
`pwd` VARCHAR(30) DEFAULT NULL
) ENGINE=INNODB DEFAULT CHARSET=utf8;


INSERT INTO `user` (`id`,`name`,`pwd`) VALUES
(1, &#39;狂神&#39;, &#39;123456&#39;),
(2, &#39;李四&#39;, &#39;123456&#39;),
(3, &#39;张三&#39;, &#39;123890&#39;)
</code></pre>
<ul>
<li><p>新建项目(创建maven父子模块)</p>
<ul>
<li><p>配置mybatis的核心配置文件</p>
<pre><code class="xml">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;
&lt;!DOCTYPE configuration
        PUBLIC &quot;-//mybatis.org//DTD Config 3.0//EN&quot;
        &quot;http://mybatis.org/dtd/mybatis-3-config.dtd&quot;&gt;
&lt;configuration&gt;
    &lt;environments default=&quot;development&quot;&gt;
        &lt;environment id=&quot;development&quot;&gt;
            &lt;transactionManager type=&quot;JDBC&quot;/&gt;
            &lt;dataSource type=&quot;POOLED&quot;&gt;
                &lt;property name=&quot;driver&quot; value=&quot;com.mysql.jdbc.Driver&quot;/&gt;
                &lt;property name=&quot;url&quot; value=&quot;jdbc:mysql://localhost:3306/mybatis?useSSL=false&amp;amp;useUnicode=true&amp;amp;characterEncoding=UTF-8&quot;/&gt;
                &lt;property name=&quot;username&quot; value=&quot;root&quot;/&gt;
                &lt;property name=&quot;password&quot; value=&quot;123456&quot;/&gt;
            &lt;/dataSource&gt;
        &lt;/environment&gt;
    &lt;/environments&gt;
    &lt;mappers&gt;
        &lt;mapper resource=&quot;com/shan/dao/UserMapper.xml&quot;/&gt;
    &lt;/mappers&gt;
&lt;/configuration&gt;
</code></pre>
</li>
<li><p>编写mybatis工具类</p>
<pre><code class="java">package com.shan.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

//sqlSessionFactory  --&gt;  sqlSession
public class MybatisUtils &#123;
    private static SqlSessionFactory sqlSessionFactory;

    static &#123;
        try &#123;
            //获取sqlSessionFactory对象
            String resource = &quot;mybatis-config.xml&quot;;
            InputStream is = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        &#125; catch (IOException e) &#123;
            e.printStackTrace();
        &#125;
    &#125;

    //既然有了sqlSessionFactory, 我们可以从中获取sqlSession实例
    //SqlSession 完全包含了面向数据库执行 SQL 命令所需要的所有方法

    public static SqlSession getSqlSession() &#123;
        return sqlSessionFactory.openSession();
    &#125;
&#125;
</code></pre>
</li>
</ul>
</li>
<li><p>编写实体类</p>
<ul>
<li><p>实体类</p>
<pre><code class="java">package com.shan.pojo;

public class User &#123;
    private int id;
    private String name;
    private String pwd;
    public User() &#123;
    &#125;
    public User(int id, String name, String pwd) &#123;
        this.id = id;
        this.name = name;
        this.pwd = pwd;
    &#125;
    public int getId() &#123;
        return id;
    &#125;
    public void setId(int id) &#123;
        this.id = id;
    &#125;
    public String getName() &#123;
        return name;
    &#125;
    public void setName(String name) &#123;
        this.name = name;
    &#125;
    public String getPwd() &#123;
        return pwd;
    &#125;
    public void setPwd(String pwd) &#123;
        this.pwd = pwd;
    &#125;
    @Override
    public String toString() &#123;
        return &quot;User&#123;&quot; +
                &quot;id=&quot; + id +
                &quot;, name=&#39;&quot; + name + &#39;\&#39;&#39; +
                &quot;, pwd=&#39;&quot; + pwd + &#39;\&#39;&#39; +
                &#39;&#125;&#39;;
    &#125;
&#125;
</code></pre>
</li>
<li><p>Dao接口</p>
<pre><code class="java">package com.shan.dao;

import com.shan.pojo.User;

import java.util.List;

public interface UserDao &#123;
    List&lt;User&gt; getUserList();
&#125;
</code></pre>
</li>
<li><p>接口实现类由原本的UserDaoOmpl转变成一个Mapper配置文件</p>
<pre><code class="xml">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;
&lt;!DOCTYPE mapper
        PUBLIC &quot;-//mybatis.org//DTD Mapper 3.0//EN&quot;
        &quot;http://mybatis.org/dtd/mybatis-3-mapper.dtd&quot;&gt;
&lt;mapper namespace=&quot;com.shan.dao.UserDao&quot;&gt;
    &lt;select id=&quot;getUserList&quot; resultType=&quot;com.shan.pojo.User&quot;&gt;
        select * from user
    &lt;/select&gt;
&lt;/mapper&gt;
</code></pre>
</li>
</ul>
</li>
<li><p>测试 (测试的包尽量一一对应)</p>
<ul>
<li><p>junit测试</p>
<pre><code class="shell"># 错误1
org.apache.ibatis.binding.BindingException: Type interface com.xiaofan.dao.UserDao is not known to the MapperRegistry.

# 解决方案
&lt;mappers&gt;
    &lt;mapper resource=&quot;com/xiaofan/dao/UserMapper.xml&quot;/&gt;
&lt;/mappers&gt;

# 错误2
Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.io.IOException: Could not find resource com/xiaofan/dao/UserMapper.xml

# 解决方案
    &lt;build&gt;
        &lt;resources&gt;
            &lt;resource&gt;
                &lt;directory&gt;src/main/resources&lt;/directory&gt;
                &lt;includes&gt;
                    &lt;include&gt;**/*.properties&lt;/include&gt;
                    &lt;include&gt;**/*.xml&lt;/include&gt;
                    &lt;include&gt;**/*.tld&lt;/include&gt;
                &lt;/includes&gt;
                &lt;filtering&gt;true&lt;/filtering&gt;
            &lt;/resource&gt;
            &lt;resource&gt;
                &lt;directory&gt;src/main/java&lt;/directory&gt;
                &lt;includes&gt;
                    &lt;include&gt;**/*.properties&lt;/include&gt;
                    &lt;include&gt;**/*.xml&lt;/include&gt;
                    &lt;include&gt;**/*.tld&lt;/include&gt;
                &lt;/includes&gt;
                &lt;filtering&gt;true&lt;/filtering&gt;
            &lt;/resource&gt;
        &lt;/resources&gt;
    &lt;/build&gt;
    
</code></pre>
</li>
</ul>
</li>
</ul>
<p>可能遇到的问题：</p>
<ol>
<li>配置文件没有注册</li>
<li>绑定接口错误</li>
<li>方法名不对</li>
<li>返回类型不对</li>
</ol>
<h1 id="CRUD"><a href="#CRUD" class="headerlink" title="CRUD"></a>CRUD</h1><h2 id="1、namespace"><a href="#1、namespace" class="headerlink" title="1、namespace"></a>1、namespace</h2><p>namespace中的包名要和Dao/Mapper接口的包名一致！</p>
<h2 id="2、select"><a href="#2、select" class="headerlink" title="2、select"></a>2、select</h2><p>选择，查询语句；</p>
<ul>
<li>id：就是对应的nameSpace中的方法名；</li>
<li>resultType：Sql语句执行的返回值！</li>
<li>parameterType：参数类型</li>
</ul>
<h2 id="增删改需要提交事务"><a href="#增删改需要提交事务" class="headerlink" title="增删改需要提交事务"></a>增删改需要提交事务</h2><pre><code class="java">sqlSession.commit();
sqlSession.close();
</code></pre>
<h2 id="3、insert-update-delete"><a href="#3、insert-update-delete" class="headerlink" title="3、insert,update,delete"></a>3、insert,update,delete</h2><pre><code class="java">int addUser(User user);
int updUser(User user);
int deleteUser(int id);
</code></pre>
<pre><code class="java">@Test
    public void addUser()&#123;
        //获得sqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int res = mapper.addUser(new User(5, &quot;haha&quot;, &quot;123456&quot;));
        if (res!=0)&#123;
            System.out.println(&quot;success&quot;);
        &#125;
        sqlSession.commit();
        sqlSession.close();
    &#125;

    @Test
    public void updUser() &#123;
        //获得sqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int res = mapper.updUser(new User(4, &quot;aa&quot;, &quot;123456&quot;));
        if (res!=0)&#123;
            System.out.println(&quot;success&quot;);
        &#125;
        sqlSession.commit();
        sqlSession.close();
    &#125;

    @Test
    public void deleteUser() &#123;
        //获得sqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int res = mapper.deleteUser(5);
        if (res!=0)&#123;
            System.out.println(&quot;success&quot;);
        &#125;
        sqlSession.commit();
        sqlSession.close();
    &#125;
</code></pre>
<pre><code class="xml">&lt;!--    对象中的属性可以直接取出来--&gt;
    &lt;insert id=&quot;addUser&quot; parameterType=&quot;com.shan.pojo.User&quot;&gt;
        insert into mybatis.user (id,name,pwd) values (#&#123;id&#125;,#&#123;name&#125;,#&#123;pwd&#125;)
    &lt;/insert&gt;

    &lt;update id=&quot;updUser&quot; parameterType=&quot;com.shan.pojo.User&quot;&gt;
        update mybatis.user set name=#&#123;name&#125;, pwd=#&#123;pwd&#125; where id=#&#123;id&#125;
    &lt;/update&gt;

    &lt;delete id=&quot;deleteUser&quot; parameterType=&quot;int&quot;&gt;
        delete from mybatis.user where id=#&#123;id&#125;
    &lt;/delete&gt;
</code></pre>
<h1 id="万能Map"><a href="#万能Map" class="headerlink" title="万能Map"></a>万能Map</h1><p>假如我们的实体类，或者数据库中的表，字段或者参数过多，我们应当考虑使用Map传入数据，而不是对象实体（User）</p>
<p>map传递参数，直接在sql中取出key即可！ parameterType=”map”</p>
<p>对象传递参数，直接在sql中取出对象的属性即可！</p>
<p>只有一个基本类型参数的情况下，可以直接在sql中取到！</p>
<p>多个参数用map, 或者注解</p>
<pre><code class="java">@Test
    public void getUserByIdandName()&#123;
        //获得sqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        HashMap&lt;String, Object&gt; objectMap = new HashMap&lt;String, Object&gt;();
        objectMap.put(&quot;userid&quot;, 7);
        objectMap.put(&quot;username&quot;, &quot;zz&quot;);
        User user = mapper.getUserByIdandName(objectMap);
        System.out.println(user.toString());
        sqlSession.close();
    &#125;
</code></pre>
<pre><code class="xml">&lt;select id=&quot;getUserByIdandName&quot;  parameterType=&quot;map&quot; resultType=&quot;com.shan.pojo.User&quot;&gt;
        select * from mybatis.user where id = #&#123;userid&#125; and name = #&#123;username&#125;
    &lt;/select&gt;
</code></pre>
<h1 id="模糊查询"><a href="#模糊查询" class="headerlink" title="模糊查询"></a>模糊查询</h1><p>不要让java传值拼接通配符<code>% _</code>，有SQL注入风险，比如传入<code>or 1=1</code>，恒定条件会导致全查出来；</p>
<p>sql map 中使用通配符；</p>
<pre><code class="xml">&lt;select id=&quot;getUserLike&quot; parameterType=&quot;string&quot; resultType=&quot;com.shan.pojo.User&quot;&gt;
        select * from mybatis.user where name like &quot;%&quot;#&#123;key&#125;&quot;%&quot;
    &lt;/select&gt;
</code></pre>
<h1 id="配置之属性优化mybatis-02"><a href="#配置之属性优化mybatis-02" class="headerlink" title="配置之属性优化mybatis-02"></a>配置之属性优化mybatis-02</h1><h2 id="核心配置文件"><a href="#核心配置文件" class="headerlink" title="核心配置文件"></a>核心配置文件</h2><ul>
<li>mybatis-config.xml</li>
<li>Mybatis的配置文件包含了会深深影响MyBatis行为的设置和属性信息。</li>
</ul>
<pre><code>configuration（配置）
    properties（属性）
    settings（设置）
    typeAliases（类型别名）
    typeHandlers（类型处理器）
    objectFactory（对象工厂）
    plugins（插件）
    environments（环境配置）
        environment（环境变量）
            transactionManager（事务管理器）
            dataSource（数据源）
    databaseIdProvider（数据库厂商标识）
    mappers（映射器）
</code></pre>
<h2 id="环境配置"><a href="#环境配置" class="headerlink" title="环境配置"></a>环境配置</h2><p>Mybatis可以配置成适应多种环境</p>
<p>不过要记住，尽管可以配置多个环境，但每个sqlsessionFactory实例只能选择一种环境</p>
<p>学会使用配置多套运行环境！—— <code>&lt;environments default=&quot;development&quot;&gt;</code></p>
<p>MyBatis默认的事务管理器就是JDBC，连接池：POOLED</p>
<h2 id="属性（properties）"><a href="#属性（properties）" class="headerlink" title="属性（properties）"></a>属性（properties）</h2><p>我们可以通过properties属性来实现引用配置文件</p>
<p>这些属性都是可外部配置且可动态替换的，既可以在典型的java属性文件中配置，也可通过properties元素的子元素来传递。  【db.properties】</p>
<p>db.properties</p>
<pre><code class="xml">driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&amp;amp;useUnicode=true&amp;amp;characterEncoding=UTF-8
username=root
password=123456
</code></pre>
<p>在mybatis-config.xml 中映入</p>
<pre><code class="xml">&lt;!--引入外部配置文件--&gt;
    &lt;properties resource=&quot;db.properties&quot;&gt;
        &lt;property name=&quot;username&quot; value=&quot;root&quot;/&gt;
    &lt;/properties&gt;
</code></pre>
<ul>
<li><p>可以直接引入外部配置文件</p>
</li>
<li><p>可以在其中增加一些配置属性</p>
</li>
<li><p>如果两个文件有同一个字段，优先使用db.properties外部配置文件的（先引入本文件属性，在引入外部文件属性，外部文件属性会覆盖本文件属性）</p>
</li>
</ul>
<h2 id="类型别名"><a href="#类型别名" class="headerlink" title="类型别名"></a>类型别名</h2><ul>
<li>类型别名是为java类型设置一个短的名字。</li>
<li>存在的意义仅在于用来减少类完全限定名的冗余。</li>
</ul>
<pre><code class="xml">&lt;!--类型别名--&gt;
    &lt;typeAliases&gt;
        &lt;typeAlias type=&quot;com.shan.pojo.User&quot; alias=&quot;User&quot;/&gt;
    &lt;/typeAliases&gt;
</code></pre>
<p>也可以指定一个包名，MyBatis会在包名下面搜索需要的Java Bean，比如：</p>
<p>扫描实体类的包，他的默认别名就为这个类的类名，首字母小写！</p>
<pre><code class="xml">    &lt;typeAliases&gt;
        &lt;package name=&quot;com.shan.pojo&quot;/&gt;
    &lt;/typeAliases&gt;
</code></pre>
<p>两种方法，在实体类比较少的时候，使用第一种方式。</p>
<p>如果实体类身份多，建议使用第二种。</p>
<p>第一种可以DIY别名，第二种则不行，如果非要改，需要在实体上增加注解。</p>
<pre><code class="java">@Alias(value = &quot;hello&quot;)
public class User &#123;&#125;
</code></pre>
<h2 id="设置-Settings"><a href="#设置-Settings" class="headerlink" title="设置 Settings"></a>设置 Settings</h2><p>这是 MyBatis 中极为重要的调整设置，它们会改变 MyBatis 的运行时行为。</p>
<p><img src="https://cdn.jsdelivr.net/gh/RhymeXmove/blogimg@latest/article/JAVA-MyBatis-20210503/2020062316474822.png"></p>
<h2 id="其他配置"><a href="#其他配置" class="headerlink" title="其他配置"></a>其他配置</h2><p>typeHandlers（类型处理器）<br>objectFactory（对象工厂）<br>plugins 插件<br>mybatis-generator-core<br>mybatis-plus<br>通用mapper</p>
<h2 id="映射器-mappers"><a href="#映射器-mappers" class="headerlink" title="映射器 mappers"></a>映射器 mappers</h2><p>MapperRegistry：注册绑定我们的Mapper文件；</p>
<p>方式一：【推荐使用】</p>
<pre><code class="xml">&lt;!--每一个Mapper.xml都需要在MyBatis核心配置文件中注册--&gt;
&lt;mappers&gt;
    &lt;mapper resource=&quot;com/kuang/dao/UserMapper.xml&quot;/&gt;
&lt;/mappers&gt;
</code></pre>
<p>方式二：使用class文件绑定注册</p>
<pre><code class="xml">&lt;!--每一个Mapper.xml都需要在MyBatis核心配置文件中注册--&gt;
&lt;mappers&gt;
    &lt;mapper class=&quot;com.kuang.dao.UserMapper&quot;/&gt;
&lt;/mappers&gt;
</code></pre>
<p>注意点：</p>
<p>接口和他的Mapper配置文件必须同名<br>接口和他的Mapper配置文件必须在同一个包下</p>
<p>方式三：使用包扫描进行注入</p>
<pre><code class="xml">&lt;mappers&gt;
    &lt;package name=&quot;com.kuang.dao&quot;/&gt;
&lt;/mappers&gt;
</code></pre>
<h2 id="作用域和生命周期"><a href="#作用域和生命周期" class="headerlink" title="作用域和生命周期"></a>作用域和生命周期</h2><p><img src="https://cdn.jsdelivr.net/gh/RhymeXmove/blogimg@latest/article/JAVA-MyBatis-20210503/20200623164809990.png"></p>
<p>声明周期和作用域是至关重要的，因为错误的使用会导致非常严重的并发问题。</p>
<p><strong>SqlSessionFactoryBuilder:</strong></p>
<p>一旦创建了SqlSessionFactory，就不再需要它了<br>局部变量<br>SqlSessionFactory:</p>
<p>说白了就可以想象为：数据库连接池<br>SqlSessionFactory一旦被创建就应该在应用的运行期间一直存在，没有任何理由丢弃它或重新创建一个实例。<br>因此SqlSessionFactory的最佳作用域是应用作用域（ApplocationContext）。<br>最简单的就是使用单例模式或静态单例模式。<br>SqlSession：</p>
<p>连接到连接池的一个请求<br>SqlSession 的实例不是线程安全的，因此是不能被共享的，所以它的最佳的作用域是请求或方法作用域。<br>用完之后需要赶紧关闭，否则资源被占用！<br><img src="https://cdn.jsdelivr.net/gh/RhymeXmove/blogimg@latest/article/JAVA-MyBatis-20210503/20200623164833872.png"></p>
<h1 id="解决属性名和字段名不一致的问题"><a href="#解决属性名和字段名不一致的问题" class="headerlink" title="解决属性名和字段名不一致的问题"></a>解决属性名和字段名不一致的问题</h1><h3 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h3><p>数据库中的字段</p>
<p><img src="https://cdn.jsdelivr.net/gh/RhymeXmove/blogimg@latest/article/JAVA-MyBatis-20210503/20200623164845962.png"></p>
<p>新建一个项目，拷贝之前的，测试实体类字段不一致的情况</p>
<p><img src="https://cdn.jsdelivr.net/gh/RhymeXmove/blogimg@latest/article/JAVA-MyBatis-20210503/20200623164853569.png"></p>
<p>测试出现问题<br><img src="https://cdn.jsdelivr.net/gh/RhymeXmove/blogimg@latest/article/JAVA-MyBatis-20210503/20200623164901861.png"></p>
<pre><code class="xml">// select * from user where id = #&#123;id&#125;
// 类型处理器
// select id,name,pwd from user where id = #&#123;id&#125;
</code></pre>
<p>解决方法：</p>
<ul>
<li>起别名</li>
</ul>
<pre><code class="xml">&lt;select id=&quot;getUserById&quot; resultType=&quot;com.kuang.pojo.User&quot;&gt;
    select id,name,pwd as password from USER where id = #&#123;id&#125;
&lt;/select&gt;
</code></pre>
<h3 id="resultMap"><a href="#resultMap" class="headerlink" title="resultMap"></a>resultMap</h3><p>结果集映射</p>
<p>id name pwd</p>
<p>id name password</p>
<pre><code class="xml">&lt;!--结果集映射--&gt;
&lt;resultMap id=&quot;UserMap&quot; type=&quot;User&quot;&gt;
    &lt;!--column数据库中的字段，property实体类中的属性--&gt;
    &lt;result column=&quot;id&quot; property=&quot;id&quot;&gt;&lt;/result&gt;
    &lt;result column=&quot;name&quot; property=&quot;name&quot;&gt;&lt;/result&gt;
    &lt;result column=&quot;pwd&quot; property=&quot;password&quot;&gt;&lt;/result&gt;
&lt;/resultMap&gt;

&lt;select id=&quot;getUserList&quot; resultMap=&quot;UserMap&quot;&gt;
    select * from USER
&lt;/select&gt;
</code></pre>
<ul>
<li><p>resultMap 元素是 MyBatis 中最重要最强大的元素。</p>
</li>
<li><p>ResultMap 的设计思想是，对简单的语句做到零配置，对于复杂一点的语句，只需要描述语句之间的关系就行了。</p>
</li>
<li><p>ResultMap 的优秀之处——你完全可以不用显式地配置它们。</p>
<p>如果这个世界总是这么简单就好了。</p>
</li>
</ul>
<h1 id="日志"><a href="#日志" class="headerlink" title="日志"></a>日志</h1><h2 id="日志工厂"><a href="#日志工厂" class="headerlink" title="日志工厂"></a>日志工厂</h2><p>如果一个数据库操作，出现了异常，我们需要排错，日志就是最好的助手！</p>
<p>曾经：sout、debug</p>
<p>现在：日志工厂</p>
<p><img src="https://cdn.jsdelivr.net/gh/RhymeXmove/blogimg@latest/article/JAVA-MyBatis-20210503/20200623164920502.png"></p>
<ul>
<li>SLF4J</li>
<li>LOG4J 【掌握】</li>
<li>LOG4J2</li>
<li>JDK_LOGGING</li>
<li>COMMONS_LOGGING</li>
<li>STDOUT_LOGGING 【掌握】</li>
<li>NO_LOGGING</li>
</ul>
<p>在MyBatis中具体使用哪一个日志实现，在设置中设定</p>
<p><strong>STDOUT_LOGGING</strong></p>
<pre><code class="xml">&lt;settings&gt;
    &lt;!--标注的日志工厂--&gt;
    &lt;setting name=&quot;logImpl&quot; value=&quot;STDOUT_LOGGING&quot;/&gt;
&lt;/settings&gt;
</code></pre>
<p><img src="https://cdn.jsdelivr.net/gh/RhymeXmove/blogimg@latest/article/JAVA-MyBatis-20210503/2020062316493391.png"></p>
<h2 id="Log4j"><a href="#Log4j" class="headerlink" title="Log4j"></a>Log4j</h2><p>什么是Log4j？</p>
<p>Log4j是Apache的一个开源项目，通过使用Log4j，我们可以控制日志信息输送的目的地是控制台、文件、GUI组件；</p>
<p>我们也可以控制每一条日志的输出格式；</p>
<p>通过定义每一条日志信息的级别，我们能够更加细致地控制日志的生成过程；</p>
<p>最令人感兴趣的就是，这些可以通过一个配置文件来灵活地进行配置，而不需要修改应用的代码。</p>
<ol>
<li>先导入log4j的包</li>
</ol>
<pre><code class="xml">&lt;dependency&gt;
    &lt;groupId&gt;log4j&lt;/groupId&gt;
    &lt;artifactId&gt;log4j&lt;/artifactId&gt;
    &lt;version&gt;1.2.17&lt;/version&gt;
&lt;/dependency&gt;
</code></pre>
<ol start="2">
<li>log4j.properties</li>
</ol>
<pre><code class="properties">#将等级为DEBUG的日志信息输出到console和file这两个目的地，console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file
​
#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/rzp.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d&#123;yy-MM-dd&#125;][%c]%m%n
#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sq1.PreparedStatement=DEBUG
</code></pre>
<ol start="3">
<li>配置settings为log4j实现</li>
<li>测试运行</li>
</ol>
<p><strong>Log4j简单使用</strong></p>
<ol>
<li>在要使用Log4j的类中，导入包 import org.apache.log4j.Logger;  //注意要导对包</li>
<li>日志对象，参数为当前类的class对象</li>
</ol>
<pre><code class="properties">Logger logger = Logger.getLogger(UserDaoTest.class);
</code></pre>
<ol start="3">
<li>日志级别</li>
</ol>
<pre><code class="properties">logger.info(&quot;info: 测试log4j&quot;);
logger.debug(&quot;debug: 测试log4j&quot;);
logger.error(&quot;error:测试log4j&quot;);
</code></pre>
<ol>
<li>info</li>
<li>debug</li>
<li>error</li>
</ol>
<h1 id="分页"><a href="#分页" class="headerlink" title="分页"></a>分页</h1><p><strong>思考：为什么分页？</strong></p>
<ul>
<li>减少数据的处理量</li>
</ul>
<h2 id="使用Limit分页"><a href="#使用Limit分页" class="headerlink" title="使用Limit分页"></a>使用Limit分页</h2><pre><code class="sql">SELECT * from user limit startIndex,pageSize   #[0,3)
</code></pre>
<p><strong>使用MyBatis实现分页，核心SQL</strong></p>
<ol>
<li><p>接口</p>
<pre><code class="java">//分页
List&lt;User&gt; getUserByLimit(Map&lt;String,Integer&gt; map);
</code></pre>
</li>
<li><p>Mapper.xml</p>
<pre><code class="xml">&lt;!-- 结果集映射 --&gt;
    &lt;resultMap id=&quot;UserMap&quot; type=&quot;User&quot;/&gt;
&lt;!--分页查询--&gt;
&lt;select id=&quot;getUserByLimit&quot; parameterType=&quot;map&quot; resultMap=&quot;UserMap&quot;&gt;
    select * from user limit #&#123;startIndex&#125;,#&#123;pageSize&#125;
&lt;/select&gt;
</code></pre>
</li>
<li><p>测试</p>
<pre><code class="java">    @Test
    public void getUserByLimit()&#123;
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        HashMap&lt;String, Integer&gt; map = new HashMap&lt;String, Integer&gt;();
        map.put(&quot;startIndex&quot;,1);
        map.put(&quot;pageSize&quot;,2);
        List&lt;User&gt; list = mapper.getUserByLimit(map);
        for (User user : list) &#123;
            System.out.println(user);
        &#125;
    &#125;
</code></pre>
</li>
</ol>
<h2 id="RowBounds分页"><a href="#RowBounds分页" class="headerlink" title="RowBounds分页"></a>RowBounds分页</h2><p>不再使用SQL实现分页，不建议在开发中使用</p>
<ol>
<li><p>接口</p>
<pre><code class="java">//分页2
    List&lt;User&gt; getUserByRowBounds();
</code></pre>
</li>
<li><p>mapper.xml</p>
<pre><code class="xml">&lt;!--分页查询2--&gt;
    &lt;select id=&quot;getUserByRowBounds&quot; resultMap=&quot;UserMap&quot;&gt;
        select * from mybatis.user
    &lt;/select&gt;
</code></pre>
</li>
<li><p>测试</p>
<pre><code class="java">@Test
    public void getUserByRowBounds()&#123;
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //RowBounds实现
        RowBounds rowBounds = new RowBounds(1, 2);
        //通过Java代码层面实现分页
        List&lt;User&gt; userList = sqlSession.selectList(&quot;com.shan.dao.UserMapper.getUserByRowBounds&quot;, null, rowBounds);
        for (User user : userList) &#123;
            System.out.println(user);
        &#125;
        sqlSession.close();
    &#125;
</code></pre>
</li>
</ol>
<h2 id="分页插件"><a href="#分页插件" class="headerlink" title="分页插件"></a>分页插件</h2><p><img src="https://cdn.jsdelivr.net/gh/RhymeXmove/blogimg@latest/article/JAVA-MyBatis-20210503/20200623164958936.png"></p>
<h1 id="使用注解开发"><a href="#使用注解开发" class="headerlink" title="使用注解开发"></a>使用注解开发</h1><h2 id="面向接口开发"><a href="#面向接口开发" class="headerlink" title="面向接口开发"></a>面向接口开发</h2><p><strong>三个面向区别</strong></p>
<ul>
<li>面向对象是指，我们考虑问题时，以对象为单位，考虑它的属性和方法；</li>
<li>面向过程是指，我们考虑问题时，以一个具体的流程（事务过程）为单位，考虑它的实现；</li>
<li>接口设计与非接口设计是针对复用技术而言的，与面向对象（过程）不是一个问题，更多的体现就是对系统整体的架构；</li>
</ul>
<h2 id="使用注解开发-1"><a href="#使用注解开发-1" class="headerlink" title="使用注解开发"></a>使用注解开发</h2><ol>
<li><p>注解在接口上实现</p>
<pre><code class="java">@Select(&quot;select * from user&quot;)
List&lt;User&gt; getUsers();
</code></pre>
</li>
<li><p>需要在核心配置文件中绑定接口</p>
<pre><code class="xml">&lt;mappers&gt;
    &lt;mapper class=&quot;com.kuang.dao.UserMapper&quot;/&gt;
&lt;/mappers&gt;
</code></pre>
</li>
<li><p>测试</p>
</li>
</ol>
<p>本质：反射机制实现</p>
<p>底层：动态代理</p>
<p><img src="https://cdn.jsdelivr.net/gh/RhymeXmove/blogimg@latest/article/JAVA-MyBatis-20210503/20200623165014965.png"></p>
<p><strong>MyBatis详细执行流程</strong></p>
<p><img src="https://cdn.jsdelivr.net/gh/RhymeXmove/blogimg@latest/article/JAVA-MyBatis-20210503/20200623165030775.png"></p>
<h2 id="注解CURD"><a href="#注解CURD" class="headerlink" title="注解CURD"></a>注解CURD</h2><pre><code class="java">//方法存在多个参数，所有的参数前面必须加上@Param(&quot;id&quot;)注解
@Delete(&quot;delete from user where id = $&#123;uid&#125;&quot;)
int deleteUser(@Param(&quot;uid&quot;) int id);
</code></pre>
<p><strong>关于@Param( )注解</strong></p>
<ul>
<li>基本类型的参数或者String类型，需要加上</li>
<li>引用类型不需要加</li>
<li>如果只有一个基本类型的话，可以忽略，但是建议大家都加上</li>
<li>我们在SQL中引用的就是我们这里的@Param()中设定的属性名</li>
</ul>
<p><strong>#{} 和 ${}</strong></p>
<h1 id="Lombok"><a href="#Lombok" class="headerlink" title="Lombok"></a>Lombok</h1><p>Lombok项目是一个Java库，它会自动插入编辑器和构建工具中，Lombok提供了一组有用的注释，用来消除Java类中的大量样板代码。仅五个字符(@Data)就可以替换数百行代码从而产生干净，简洁且易于维护的Java类。</p>
<p>使用步骤：</p>
<ol>
<li><p>在IDEA中安装Lombok插件; file–setting–plugin – 搜索安装lombok插件</p>
</li>
<li><p>在项目中导入lombok的jar包</p>
</li>
</ol>
<pre><code class="xml">&lt;dependency&gt;
    &lt;groupId&gt;org.projectlombok&lt;/groupId&gt;
    &lt;artifactId&gt;lombok&lt;/artifactId&gt;
    &lt;version&gt;1.18.10&lt;/version&gt;
    &lt;scope&gt;provided&lt;/scope&gt;
&lt;/dependency&gt;
</code></pre>
<ol start="3">
<li>在程序上加注解</li>
</ol>
<pre><code>@Getter and @Setter
@FieldNameConstants
@ToString
@EqualsAndHashCode
@AllArgsConstructor, @RequiredArgsConstructor and @NoArgsConstructor
@Log, @Log4j, @Log4j2, @Slf4j, @XSlf4j, @CommonsLog, @JBossLog, @Flogger, @CustomLog
@Data //无参构造，get，set，tostring，hashcode，equals
@Builder
@SuperBuilder
@Singular
@Delegate
@Value
@Accessors
@Wither
@With
@SneakyThrows
@val
</code></pre>
<p>说明</p>
<pre><code class="java">@Data
@AllArgsConstructor
@NoArgsConstructor
public class User &#123;
    private int id;
    private String name;
    private String password;
&#125;
</code></pre>
<h1 id="多对一处理"><a href="#多对一处理" class="headerlink" title="多对一处理"></a>多对一处理</h1><pre><code class="sql">CREATE TABLE `teacher` (
                           `id` INT(10) NOT NULL,
                           `name` VARCHAR(30) DEFAULT NULL,
                           PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

INSERT INTO teacher(`id`, `name`) VALUES (1, &#39;秦老师&#39;);

CREATE TABLE `student` (
                           `id` INT(10) NOT NULL,
                           `name` VARCHAR(30) DEFAULT NULL,
                           `tid` INT(10) DEFAULT NULL,
                           PRIMARY KEY (`id`),
                           KEY `fktid` (`tid`),
                           CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

INSERT INTO `student` (`id`, `name`, `tid`) VALUES (1, &#39;小明&#39;, 1);
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (2, &#39;小红&#39;, 1);
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (3, &#39;小张&#39;, 1);
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (4, &#39;小李&#39;, 1);
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (5, &#39;小王&#39;, 1);

alter table student ADD CONSTRAINT fk_tid foreign key (tid) references teacher(id)
</code></pre>
<p>多个学生一个老师；</p>
<pre><code class="sql">alter table student ADD CONSTRAINT fk_tid foreign key (tid) references teacher(id)
</code></pre>
<h1 id="一对多处理"><a href="#一对多处理" class="headerlink" title="一对多处理"></a>一对多处理</h1><blockquote>
<p>一个老师多个学生；</p>
<p>对于老师而言，就是一对多的关系；</p>
</blockquote>
<h2 id="环境搭建"><a href="#环境搭建" class="headerlink" title="环境搭建"></a>环境搭建</h2><p><strong>实体类</strong></p>
<pre><code class="java">@Data
public class Student &#123;
    private int id;
    private String name;
    private int tid;
&#125;
</code></pre>
<pre><code class="java">@Data
public class Teacher &#123;
    private int id;
    private String name;

    //一个老师拥有多个学生
    private List&lt;Student&gt; students;
&#125;
</code></pre>
<pre><code class="java">&lt;!--按结果嵌套查询--&gt;
&lt;select id=&quot;getTeacher&quot; resultMap=&quot;StudentTeacher&quot;&gt;
    SELECT s.id sid, s.name sname,t.name tname,t.id tid FROM student s, teacher t
    WHERE s.tid = t.id AND tid = #&#123;tid&#125;
&lt;/select&gt;
&lt;resultMap id=&quot;StudentTeacher&quot; type=&quot;Teacher&quot;&gt;
    &lt;result property=&quot;id&quot; column=&quot;tid&quot;/&gt;
    &lt;result property=&quot;name&quot; column=&quot;tname&quot;/&gt;
    &lt;!--复杂的属性，我们需要单独处理 对象：association 集合：collection
    javaType=&quot;&quot;指定属性的类型！
    集合中的泛型信息，我们使用ofType获取
    --&gt;
    &lt;collection property=&quot;students&quot; ofType=&quot;Student&quot;&gt;
        &lt;result property=&quot;id&quot; column=&quot;sid&quot;/&gt;
        &lt;result property=&quot;name&quot; column=&quot;sname&quot;/&gt;
        &lt;result property=&quot;tid&quot; column=&quot;tid&quot;/&gt;
    &lt;/collection&gt;
&lt;/resultMap&gt;
</code></pre>
<h3 id="小结"><a href="#小结" class="headerlink" title="小结"></a>小结</h3><ol>
<li>关联 - association 【多对一】</li>
<li>集合 - collection 【一对多】</li>
<li>javaType &amp; ofType<ol>
<li>JavaType用来指定实体类中的类型</li>
<li>ofType用来指定映射到List或者集合中的pojo类型，泛型中的约束类型</li>
</ol>
</li>
</ol>
<p> <strong>注意点：</strong></p>
<ul>
<li><p>保证SQL的可读性，尽量保证通俗易懂</p>
</li>
<li><p>注意一对多和多对一，属性名和字段的问题</p>
</li>
<li><p>如果问题不好排查错误，可以使用日志，建议使用Log4</p>
<p>面试高频</p>
<ul>
<li>Mysql引擎</li>
<li>InnoDB底层原理</li>
<li>索引</li>
<li>索引优化</li>
<li></li>
</ul>
</li>
</ul>
<h1 id="动态SQL"><a href="#动态SQL" class="headerlink" title="动态SQL"></a>动态SQL</h1><p>什么是动态SQL：动态SQL就是根据不同的条件生成不同的SQL语句</p>
<p>所谓的动态SQL，本质上还是SQL语句，只是我们可以在SQL层面，去执行一个逻辑代码</p>
<p>动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架，你应该能理解根据不同条件拼接 SQL 语句有多痛苦，例如拼接时要确保不能忘记添加必要的空格，还要注意去掉列表最后一个列名的逗号。利用动态 SQL，可以彻底摆脱这种痛苦。</p>
<h2 id="搭建环境"><a href="#搭建环境" class="headerlink" title="搭建环境"></a>搭建环境</h2><pre><code class="sql">CREATE TABLE `mybatis`.`blog`  (
  `id` int(10) NOT NULL AUTO_INCREMENT COMMENT &#39;博客id&#39;,
  `title` varchar(30) NOT NULL COMMENT &#39;博客标题&#39;,
  `author` varchar(30) NOT NULL COMMENT &#39;博客作者&#39;,
  `create_time` datetime(0) NOT NULL COMMENT &#39;创建时间&#39;,
  `views` int(30) NOT NULL COMMENT &#39;浏览量&#39;,
  PRIMARY KEY (`id`)
)
</code></pre>
<p>创建一个基础工程</p>
<ol>
<li>导包</li>
<li>编写配置文件</li>
<li>编写实体类</li>
</ol>
<pre><code class="java">@Data
public class Blog &#123;
    private int id;
    private String title;
    private String author;

    private Date createTime;// 属性名和字段名不一致
    private int views;
&#125;
</code></pre>
<ol start="4">
<li>编写实体类对应Mapper接口和Mapper.xml文件</li>
</ol>
<h3 id="IF"><a href="#IF" class="headerlink" title="IF"></a>IF</h3><pre><code class="java">&lt;select id=&quot;queryBlogIF&quot; parameterType=&quot;map&quot; resultType=&quot;blog&quot;&gt;
    select * from blog
    &lt;where&gt;
        &lt;if test=&quot;title!=null&quot;&gt;
            and title = #&#123;title&#125;
        &lt;/if&gt;
        &lt;if test=&quot;author!=null&quot;&gt;
            and author = #&#123;author&#125;
        &lt;/if&gt;
    &lt;/where&gt;
&lt;/select&gt;
</code></pre>
<h3 id="choose-when-otherwise"><a href="#choose-when-otherwise" class="headerlink" title="choose (when, otherwise)"></a>choose (when, otherwise)</h3><h3 id="trim、where、set"><a href="#trim、where、set" class="headerlink" title="trim、where、set"></a>trim、where、set</h3><h3 id="SQL片段"><a href="#SQL片段" class="headerlink" title="SQL片段"></a>SQL片段</h3><p>有的时候，我们可能会将一些功能的部分抽取出来，方便服用！</p>
<ol>
<li><p>使用SQL标签抽取公共部分可</p>
<pre><code class="xml">&lt;sql id=&quot;if-title-author&quot;&gt;
    &lt;if test=&quot;title!=null&quot;&gt;
        title = #&#123;title&#125;
    &lt;/if&gt;
    &lt;if test=&quot;author!=null&quot;&gt;
        and author = #&#123;author&#125;
    &lt;/if&gt;
&lt;/sql&gt;
</code></pre>
<ol start="2">
<li><p>在需要使用的地方使用Include标签引用即可</p>
<pre><code class="xml">&lt;select id=&quot;queryBlogIF&quot; parameterType=&quot;map&quot; resultType=&quot;blog&quot;&gt;
    select * from blog
    &lt;where&gt;
        &lt;include refid=&quot;if-title-author&quot;&gt;&lt;/include&gt;
    &lt;/where&gt;
&lt;/select&gt;
</code></pre>
</li>
</ol>
</li>
</ol>
<p>注意事项：</p>
<ul>
<li>最好基于单标来定义SQL片段</li>
<li>不要存在where标签</li>
</ul>
<p><strong>动态SQL就是在拼接SQL语句，我们只要保证SQL的正确性，按照SQL的格式，去排列组合就可以了</strong></p>
<p>建议：</p>
<ul>
<li>先在Mysql中写出完整的SQL，再对应的去修改成我们的动态SQL实现通用即可</li>
</ul>
<h1 id="缓存"><a href="#缓存" class="headerlink" title="缓存"></a>缓存</h1><h2 id="简介-1"><a href="#简介-1" class="headerlink" title="简介"></a>简介</h2><p>查询 ： 连接数据库，耗资源</p>
<p> 一次查询的结果，给他暂存一个可以直接取到的地方 –&gt; 内存：缓存</p>
<p>我们再次查询的相同数据的时候，直接走缓存，不走数据库了</p>
<ol>
<li>什么是缓存[Cache]？<ol>
<li>存在内存中的临时数据</li>
<li>将用户经常查询的数据放在缓存（内存）中，用户去查询数据就不用从磁盘上（关系型数据库文件）查询，从缓存中查询，从而提高查询效率，解决了高并发系统的性能问题</li>
</ol>
</li>
<li>为什么使用缓存？<ol>
<li>减少和数据库的交互次数，减少系统开销，提高系统效率</li>
</ol>
</li>
<li>什么样的数据可以使用缓存？<ol>
<li>经常查询并且不经常改变的数据 【可以使用缓存】</li>
</ol>
</li>
</ol>
<h2 id="MyBatis缓存"><a href="#MyBatis缓存" class="headerlink" title="MyBatis缓存"></a>MyBatis缓存</h2><ul>
<li>MyBatis包含一个非常强大的查询缓存特性，它可以非常方便的定制和配置缓存，缓存可以极大的提高查询效率。</li>
<li>MyBatis系统中默认定义了两级缓存：<strong>一级缓存</strong>和<strong>二级缓存</strong><ul>
<li>默认情况下，只有一级缓存开启（SqlSession级别的缓存，也称为本地缓存）</li>
<li>二级缓存需要手动开启和配置，他是基于namespace级别的缓存。</li>
<li>为了提高可扩展性，MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来定义二级缓存。</li>
</ul>
</li>
</ul>
<h2 id="一级缓存"><a href="#一级缓存" class="headerlink" title="一级缓存"></a>一级缓存</h2><ul>
<li>一级缓存也叫本地缓存：SqlSession<ul>
<li>与数据库同一次会话期间查询到的数据会放在本地缓存中</li>
<li>以后如果需要获取相同的数据，直接从缓存中拿，没必要再去查询数据库</li>
</ul>
</li>
</ul>
<p>测试步骤：</p>
<ol>
<li><p>开启日志</p>
</li>
<li><p>测试在一个Session中查询两次记录</p>
<pre><code class="java">@Test
public void test1() &#123;
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.getUserById(1);
        System.out.println(user);

        System.out.println(&quot;=====================================&quot;);

        User user2 =  mapper.getUserById(1);
        System.out.println(user2 == user);
    &#125;
</code></pre>
</li>
<li><p>查看日志输出</p>
<p><img src="https://cdn.jsdelivr.net/gh/RhymeXmove/blogimg@latest/article/JAVA-MyBatis-20210503/20200623165129955.png"></p>
</li>
</ol>
<p><strong>缓存失效的情况：</strong></p>
<ol>
<li>查询不同的东西</li>
<li>增删改操作，可能会改变原来的数据，所以必定会刷新缓存</li>
<li>查询不同的Mapper.xml</li>
<li>手动清理缓存</li>
</ol>
<pre><code class="java">sqlSession.clearCache();
</code></pre>
<h2 id="二级缓存"><a href="#二级缓存" class="headerlink" title="二级缓存"></a>二级缓存</h2><ul>
<li>二级缓存也叫全局缓存，一级缓存作用域太低了，所以诞生了二级缓存</li>
<li>基于namespace级别的缓存，一个名称空间，对应一个二级缓存</li>
<li>工作机制<ul>
<li>一个会话查询一条数据，这个数据就会被放在当前会话的一级缓存中</li>
<li>如果会话关闭了，这个会员对应的一级缓存就没了；但是我们想要的是，会话关闭了，一级缓存中的数据被保存到二级缓存中</li>
<li>新的会话查询信息，就可以从二级缓存中获取内容</li>
<li>不同的mapper查询出的数据会放在自己对应的缓存（map）中</li>
</ul>
</li>
</ul>
<p>一级缓存开启（SqlSession级别的缓存，也称为本地缓存）</p>
<ul>
<li>二级缓存需要手动开启和配置，他是基于namespace级别的缓存。</li>
<li>为了提高可扩展性，MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来定义二级缓存。</li>
<li></li>
</ul>
<p>步骤：</p>
<ol>
<li><p>开启全局缓存</p>
<pre><code class="xml">&lt;!--显示的开启全局缓存--&gt;
&lt;setting name=&quot;cacheEnabled&quot; value=&quot;true&quot;/&gt;
</code></pre>
</li>
<li><p>在Mapper.xml中使用缓存</p>
<pre><code class="xml">&lt;!--在当前Mapper.xml中使用二级缓存--&gt;
&lt;cache
       eviction=&quot;FIFO&quot;  //first input first output
       flushInterval=&quot;60000&quot;
       size=&quot;512&quot;
       readOnly=&quot;true&quot;/&gt;
</code></pre>
</li>
<li><p>测试</p>
<ol>
<li>问题：我们需要将实体类序列化，否则就会报错</li>
</ol>
</li>
</ol>
<p><strong>小结：</strong></p>
<ul>
<li>只要开启了二级缓存，在同一个Mapper下就有效</li>
<li>所有的数据都会放在一级缓存中</li>
<li>只有当前会话提交，或者关闭的时候，才会提交到二级缓存中</li>
</ul>
<h2 id="缓存原理"><a href="#缓存原理" class="headerlink" title="缓存原理"></a>缓存原理</h2><p><img src="https://cdn.jsdelivr.net/gh/RhymeXmove/blogimg@latest/article/JAVA-MyBatis-20210503/20200623165404113.png"></p>
<p><strong>注意：</strong></p>
<ul>
<li>只有查询才有缓存，根据数据是否需要缓存（修改是否频繁选择是否开启）useCache=“true”</li>
</ul>
<pre><code class="xml">    &lt;select id=&quot;getUserById&quot; resultType=&quot;user&quot; useCache=&quot;true&quot;&gt;
        select * from user where id = #&#123;id&#125;
    &lt;/select&gt;
</code></pre>
<h2 id="自定义缓存-ehcache"><a href="#自定义缓存-ehcache" class="headerlink" title="自定义缓存-ehcache"></a>自定义缓存-ehcache</h2><p>Ehcache是一种广泛使用的开源Java分布式缓存。主要面向通用缓存</p>
<ol>
<li><p>导包</p>
<pre><code class="xml">&lt;dependency&gt;
    &lt;groupId&gt;org.mybatis.caches&lt;/groupId&gt;
    &lt;artifactId&gt;mybatis-ehcache&lt;/artifactId&gt;
    &lt;version&gt;1.2.1&lt;/version&gt;
&lt;/dependency&gt;
</code></pre>
</li>
<li><p>在mapper中指定使用我们的ehcache缓存实现</p>
<pre><code class="xml">&lt;cache type=&quot;org.mybatis.caches.ehcache.EhcacheCache&quot;/&gt;
</code></pre>
</li>
<li><p>resource/ehcache.xml</p>
</li>
</ol>
<pre><code class="xml">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;ehcache xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
         xsi:noNamespaceSchemaLocation=&quot;http://ehcache.org/ehcache.xsd&quot;
         updateCheck=&quot;false&quot;&gt;
    &lt;!--
       diskStore：为缓存路径，ehcache分为内存和磁盘两级，此属性定义磁盘的缓存位置。参数解释如下：
       user.home – 用户主目录
       user.dir  – 用户当前工作目录
       java.io.tmpdir – 默认临时文件路径
     --&gt;
    &lt;diskStore path=&quot;java.io.tmpdir/Tmp_EhCache&quot;/&gt;
    &lt;!--
       defaultCache：默认缓存策略，当ehcache找不到定义的缓存时，则使用这个缓存策略。只能定义一个。
     --&gt;
    &lt;!--
      name:缓存名称。
      maxElementsInMemory:缓存最大数目
      maxElementsOnDisk：硬盘最大缓存个数。
      eternal:对象是否永久有效，一但设置了，timeout将不起作用。
      overflowToDisk:是否保存到磁盘，当系统当机时
      timeToIdleSeconds:设置对象在失效前的允许闲置时间（单位：秒）。仅当eternal=false对象不是永久有效时使用，可选属性，默认值是0，也就是可闲置时间无穷大。
      timeToLiveSeconds:设置对象在失效前允许存活时间（单位：秒）。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用，默认是0.，也就是对象存活时间无穷大。
      diskPersistent：是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
      diskSpoolBufferSizeMB：这个参数设置DiskStore（磁盘缓存）的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
      diskExpiryThreadIntervalSeconds：磁盘失效线程运行时间间隔，默认是120秒。
      memoryStoreEvictionPolicy：当达到maxElementsInMemory限制时，Ehcache将会根据指定的策略去清理内存。默认策略是LRU（最近最少使用）。你可以设置为FIFO（先进先出）或是LFU（较少使用）。
      clearOnFlush：内存数量最大时是否清除。
      memoryStoreEvictionPolicy:可选策略有：LRU（最近最少使用，默认策略）、FIFO（先进先出）、LFU（最少访问次数）。
      FIFO，first in first out，这个是大家最熟的，先进先出。
      LFU， Less Frequently Used，就是上面例子中使用的策略，直白一点就是讲一直以来最少被使用的。如上面所讲，缓存的元素有一个hit属性，hit值最小的将会被清出缓存。
      LRU，Least Recently Used，最近最少使用的，缓存的元素有一个时间戳，当缓存容量满了，而又需要腾出地方来缓存新的元素的时候，那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。
   --&gt;
    &lt;defaultCache
            eternal=&quot;false&quot;
            maxElementsInMemory=&quot;10000&quot;
            overflowToDisk=&quot;false&quot;
            diskPersistent=&quot;false&quot;
            timeToIdleSeconds=&quot;1800&quot;
            timeToLiveSeconds=&quot;259200&quot;
            memoryStoreEvictionPolicy=&quot;LRU&quot;/&gt;

    &lt;cache
            name=&quot;cloud_user&quot;
            eternal=&quot;false&quot;
            maxElementsInMemory=&quot;5000&quot;
            overflowToDisk=&quot;false&quot;
            diskPersistent=&quot;false&quot;
            timeToIdleSeconds=&quot;1800&quot;
            timeToLiveSeconds=&quot;1800&quot;
            memoryStoreEvictionPolicy=&quot;LRU&quot;/&gt;
&lt;/ehcache&gt;
</code></pre>
<ol start="4">
<li>MyCache.java 重写 其中方法</li>
</ol>
<pre><code class="java">package com.shan.utils;

import org.apache.ibatis.cache.Cache;

import java.util.concurrent.locks.ReadWriteLock;

public class MyCache implements Cache &#123;
    public String getId() &#123;
        return null;
    &#125;

    public void putObject(Object o, Object o1) &#123;

    &#125;

    public Object getObject(Object o) &#123;
        return null;
    &#125;

    public Object removeObject(Object o) &#123;
        return null;
    &#125;

    public void clear() &#123;

    &#125;

    public int getSize() &#123;
        return 0;
    &#125;

    public ReadWriteLock getReadWriteLock() &#123;
        return null;
    &#125;
&#125;
</code></pre>
<p>现在一般用 Redis做缓存！ &lt;K, V&gt;</p>

  </article>

  
    
  <div class="nexmoe-post-copyright">
    <strong>本文作者：</strong>shanX<br>
    <strong>本文链接：</strong><a href="https://rhymexmove.github.io/2021/05/03/5fd29565f315/" title="https:&#x2F;&#x2F;rhymexmove.github.io&#x2F;2021&#x2F;05&#x2F;03&#x2F;5fd29565f315&#x2F;" target="_blank" rel="noopener">https:&#x2F;&#x2F;rhymexmove.github.io&#x2F;2021&#x2F;05&#x2F;03&#x2F;5fd29565f315&#x2F;</a><br>
    
      <strong>版权声明：</strong>本文采用 <a href="https://creativecommons.org/licenses/by-nc-sa/3.0/cn/deed.zh" target="_blank">CC BY-NC-SA 3.0 CN</a> 协议进行许可
    
  </div>


  
  
  <div class="nexmoe-post-meta nexmoe-rainbow">
    
        <a class="nexmoefont icon-appstore-fill -link" href="/categories/java/">java</a>
    
    
        <a class="nexmoefont icon-tag-fill -none-link" href="/tags/%E7%8B%82%E7%A5%9E%E8%AF%B4/" rel="tag">狂神说</a>
    
</div>

  <div class="nexmoe-post-footer">
    <section class="nexmoe-comment">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/gitalk@1.7.2/dist/gitalk.min.css">
<div id="gitalk"></div>
<script src="https://cdn.jsdelivr.net/npm/gitalk@1.7.2/dist/gitalk.min.js"></script>
<script type="text/javascript">
    var gitalk = new Gitalk({
        clientID: 'a2d666d91d6af126f538',
        clientSecret: '9c79e44494cd9fae312629457ae9b534e01a963e',
        id: decodeURI(window.location.pathname),
        repo: 'RhymeXmove.github.io',
        owner: 'RhymeXmove',
        admin: 'RhymeXmove'
    })
    gitalk.render('gitalk')
</script>
</section>
  </div>
</div>
                            <div class="nexmoe-post-right">
                                <div class="nexmoe-fixed">
                                    <div class="nexmoe-tool">
                                        <a href="#nexmoe-content" class="toc-link" aria-label="回到顶部" title="top"><button class="mdui-fab mdui-ripple"><i class="nexmoefont icon-caret-top"></i></button></a>
                                    </div>
                                </div>
                            </div>
                    </div>
                </div>
                <script src="https://cdn.jsdelivr.net/combine/npm/lazysizes@5.1.0/lazysizes.min.js,gh/highlightjs/cdn-release@9.15.8/build/highlight.min.js,npm/mdui@0.4.3/dist/js/mdui.min.js?v=1"></script>
<script>
	hljs.initHighlightingOnLoad();
</script>

<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js"></script>


<script src="https://cdn.jsdelivr.net/gh/xtaodada/xtaodada.github.io@0.0.2/copy.js"></script>
 

<script src="/js/app.js?v=1649858550912"></script>

<script src="https://cdn.jsdelivr.net/npm/justifiedGallery@3.8.1/dist/js/jquery.justifiedGallery.min.js"></script>
<script>
	$(".justified-gallery").justifiedGallery({
		rowHeight: 160,
		margins: 10,
	});
</script>

                    





        </body>

</html>